#pragma once
#include <iostream>
#include <vector>
#include "Sem.hpp"
#include <pthread.h>
namespace RingBufferModule
{
    using namespace SemModule;
    using namespace std;
    template <class T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap)
            : _ring(cap), _cap(cap), _p_step(0), _c_step(0),_datasem(0),_spacesem(_cap)
        {
            pthread_mutex_init(&_p_lock,nullptr);
            pthread_mutex_init(&_c_lock,nullptr);
        }
        void Equeue(const T &in)
        {
            // 生产者
            // pthread_mutex_lock(&_p_lock);//先锁还是先信号量？？？ 先信号量效率更高为什么？就类似于并发申请互斥量(买票)，然后在申请锁(检票)
            _spacesem.P();
            pthread_mutex_lock(&_p_lock);

            _ring[_p_step] = in; // 生产完毕
            _p_step++;
            _p_step %= _cap; // 维持唤醒特性

            pthread_mutex_unlock(&_p_lock);
            _datasem.V();
        }
        void Pop(T *out)
        {
            // 消费者
            _datasem.P();
            pthread_mutex_lock(&_c_lock);

            *out = _ring[_c_step];
            _c_step++;
            _c_step %= _cap;

            pthread_mutex_unlock(&_c_lock);
            _spacesem.V();

        }

        ~RingBuffer()
        {
            pthread_mutex_destroy(&_p_lock);
            pthread_mutex_destroy(&_c_lock);
        }
    private:
        vector<T> _ring; // 环,临界资源
        int _cap;        // 总容量
        int _p_step;     // 生产者位置
        int _c_step;     // 消费者位置
        Sem _datasem;  // 数据信号量
        Sem _spacesem; // 空间信号量

        pthread_mutex_t _p_lock; //生产者的锁
        pthread_mutex_t _c_lock; //消费者的锁
    };
}